#include "PrecompiledHeaders.h"
#include "Joystick.h"

#define NONE (0)
#define NEXT (1)
#define PREVIOUS (2)

Joystick::Joystick(OIS::JoyStick *j) : UserControlledInputDevice()
{
    joystick = j;
    x_factor = Constants::MAX_ANGLE.valueRadians() / 32768;
    y_factor = Constants::MAX_ANGLE.valueRadians() / 32768;
    int i;
    for(i = 0; i < JOYSTICK_SMOOTH_SIZE; i++)
    {
        x[i] = 0;
        y[i] = 0;
    }
    x_mean = 0.0;
    y_mean = 0.0;
    x_index = 0;
    y_index = 0;
    joystick->setEventCallback(this);
    trigger_down = quit_pressed = false;
    previous_X_pos = previous_Y_pos = NONE;
}

/*
 * initialise previous_x and previous_y
 */
void Joystick::initialise()
{
    roll  = Ogre::Radian(joystick->getJoyStickState().mAxes[2].abs * -x_factor);
    pitch = Ogre::Radian(joystick->getJoyStickState().mAxes[1].abs * -y_factor);
}

Ogre::Radian Joystick::getX()
{
    x_mean -= x[x_index] / JOYSTICK_SMOOTH_SIZE;
    x[x_index] = joystick->getJoyStickState().mAxes[2].abs;
    x_mean += x[x_index] / JOYSTICK_SMOOTH_SIZE;
    x_index++;
    if(x_index == JOYSTICK_SMOOTH_SIZE) x_index = 0;
    return Ogre::Radian(x_mean);
}

Ogre::Radian Joystick::getY()
{ 
    y_mean -= y[y_index] / JOYSTICK_SMOOTH_SIZE;
    y[y_index] = joystick->getJoyStickState().mAxes[1].abs;
    y_mean += y[y_index] / JOYSTICK_SMOOTH_SIZE;
    y_index++;
    if(y_index == JOYSTICK_SMOOTH_SIZE) y_index = 0;
    return Ogre::Radian(y_mean);
}

bool Joystick::buttonPressed(const OIS::JoyStickEvent &e, int i)
{
    switch(i)
    {
        case 0: // trigger
            trigger_down = true;
            break;
        case 1: // top buttons
        case 2:
        case 3:
        case 4:
            quit_pressed = true;
            break;
        default:
            break;
    }
    return true;
}

bool Joystick::buttonReleased(const OIS::JoyStickEvent &e, int i)
{
    switch(i)
    {
        case 0: // trigger
            trigger_down = false;
            break;
        case 1: // top buttons
        case 2:
        case 3:
        case 4:
            quit_pressed = false;
            break;
        default:
            break;
    }
    return true;
}

bool Joystick::axisMoved(const OIS::JoyStickEvent &e, int i)
{
    int next_X_pos = NONE, next_Y_pos = NONE;
    switch(i)
    {
        case 1: // Y axis = up/down
            if(e.state.mAxes[1].abs > 16000) next_Y_pos = NEXT;
            else if(e.state.mAxes[1].abs < -16000) next_Y_pos = PREVIOUS;
            if(previous_Y_pos != next_Y_pos)
            {
                if(next_Y_pos == NEXT) go_next = true;
                if(next_Y_pos == PREVIOUS) go_previous = true;
                previous_Y_pos = next_Y_pos;
            }
            break;
        case 2: // X axis = left/right
            if(e.state.mAxes[2].abs < -16000) next_X_pos = PREVIOUS;
            else if(e.state.mAxes[2].abs > 16000) next_X_pos = NEXT;
            if(previous_X_pos != next_X_pos)
            {
                if(next_X_pos == NEXT) go_next = true;
                if(next_X_pos == PREVIOUS) go_previous = true;
                previous_X_pos = next_X_pos;
            }
            break;
        case 0: // roller at front
            break;
    }
    return true;
}

bool Joystick::next()
{
    bool ret = go_next;
    go_next = false;
    return ret;
}

bool Joystick::previous()
{
    bool ret = go_previous;
    go_previous = false;
    return ret;
}

bool Joystick::quit()
{
    bool ret = quit_pressed;
    quit_pressed = false;
    return ret;
}

bool Joystick::triggerPressed()
{
    bool ret = trigger_down;
    trigger_down = false;
    return ret;
}
